//
//  File.swift
//
//
//  Created by didi on 2022/9/14.
//

import Molecular
import MolecularObjects
import MolecularUserObjects
import Vapor

struct UserAccountSessionAuthenticator: AsyncSessionAuthenticator {
    typealias User = MUser

    func respond(to request: Request, chainingTo next: AsyncResponder) async throws -> Response {
        if let sessionId = request.session.authenticated(User.self) {
            try await authenticate(sessionID: sessionId, for: request)
        }

        let response = try await next.respond(to: request)
        if let user = request.auth.get(User.self) {
            request.session.authenticate(user)
        } else if request.hasSession {
            request.session.unauthenticate(User.self)
        }

        return response
    }

    func authenticate(sessionID: UUID, for request: Request) async throws {
        guard let model = try await request.user.account.repository.get(sessionID) else { return }

        let roles = try await request.user.role.repository.findWithPermissions(model.uuid, request)
        let isRoot = !roles.filter { $0.key == MolecularUserObjects.User.Role.Keys.Root }.isEmpty
        return request.auth.login(MUser(id: model.uuid, level: isRoot ? .root : .authenticated, roles: roles))
    }
}
